﻿using System;
using System.Collections.ObjectModel;
using System.Threading;
using System.Windows;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Threading;
using _1906Ultras.Helpers;
using _1906Ultras.Model;

namespace _1906Ultras.ViewModel
{
    /// <summary>
    /// This class contains properties that the main View can data bind to.
    /// <para>
    /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
    /// </para>
    /// <para>
    /// You can also use Blend to data bind with the tool's support.
    /// </para>
    /// <para>
    /// See http://www.galasoft.ch/mvvm/getstarted
    /// </para>
    /// </summary>
    public class MainViewModel : MasterViewModel
    {
        private bool isLoaded;

        private long _oldestTweetId;
        private long _newestTweetId;
        private const int PageSize = 20;

        private static ViewModelBase _instance;
        public static ViewModelBase Instance
        {
            get { return _instance; }
            set { _instance = value; }
        }

        public static void CreateNew()
        {
            if (_instance == null)
            {
                _instance = new MainViewModel();
            }
        }

        public string ApplicationTitle
        {
            get { return "1906 Ultras"; }
        }

        private INavigationService _navigationService;
        public RelayCommand LoadedCommand { get; private set; }
        public RelayCommand<Song> SongPageCommand { get; private set; }
        public RelayCommand EventPageCommand { get; private set; }
        public RelayCommand MoreTweetsCommand { get; private set; }
        public RelayCommand RefreshTweetsCommand { get; private set; }
        /// <summary>
        /// Initializes a new instance of the MainViewModel class.
        /// </summary>
        public MainViewModel()
        {
            _navigationService = new NavigationService();
            LoadedCommand = new RelayCommand(PageLoaded);
            SongPageCommand = new RelayCommand<Song>(GoToSongPage);
            EventPageCommand = new RelayCommand(GoToEventPage);
            MoreTweetsCommand = new RelayCommand(ShowMoreTweets);
            RefreshTweetsCommand = new RelayCommand(LoadFeed);
            if (IsInDesignMode)
            {
                // Code runs in Blend --> create design time data.
            }
            else
            {
                // Code runs "for real"
            }
            
        }


        
        

        private void PageLoaded()
        {
            if (isLoaded) return;

            //new ThreadStart(() =>
            //                    {
                                    SongHelper sh = new SongHelper();
                                    sh.GetSongs((x) => SongList = x);


                                    PhotoHelper ph = new PhotoHelper();
                                    ph.GetPhotos((x) => Photos = x);


                                    EventHelper eh = new EventHelper();
                                    eh.GetEvents((x) => Events = x);

                                    LoadFeed();
                                //}).Invoke();
            
            
            isLoaded = true;
        }



        private void LoadFeed()
        {
            RefreshTweetValues();
            var th = new TwitterHelper();
            if (HelperBase.IsErrorState) HelperBase.IsErrorState = false;
            th.LoadFeed(_newestTweetId, 0, UpdateFeedTop);    
           
        }

        
        private void ShowMoreTweets()
        {
            RefreshTweetValues();
            var th = new TwitterHelper();
            if(HelperBase.IsErrorState) HelperBase.IsErrorState = false;
            th.LoadFeed(0, _oldestTweetId-1, UpdateFeedBottom);
        }

        private void RefreshTweetValues()
        {
            if (Tweets != null && Tweets.Count > 0)
            {
                _oldestTweetId = Tweets[Tweets.Count - 1].id;
                _newestTweetId = Tweets[0].id;
            }
        }

        private void UpdateFeedTop(ObservableCollection<Tweet> tweets)
        {
            UpdateFeed(tweets, FeedLocation.Top);
        }

        private void UpdateFeedBottom(ObservableCollection<Tweet> tweets )
        {
            UpdateFeed(tweets, FeedLocation.Bottom);
        }

        private void UpdateFeed(ObservableCollection<Tweet> tweets, FeedLocation location )
        {
            //if (tweets.Count == 0) return;
            if (Tweets == null)
            {
                Tweets = tweets;
                return;
            }

            switch (location)
            {
                case FeedLocation.Top:
                    for (int i = tweets.Count - 1; i >= 0; i--)
                    {
                        Tweets.Insert(0, tweets[i]);
                    }
                    break;

                case FeedLocation.Bottom:
                    foreach (var tweet in tweets)
                    {
                        Tweets.Add(tweet);
                    }
                    break;
            }

        }


        private void GoToSongPage(Song s)
        {
            _navigationService.NavigateTo(new Uri("/SongPage.xaml", UriKind.Relative));
        }


        private void GoToEventPage()
        {
            _navigationService.NavigateTo(new Uri("/EventPage.xaml", UriKind.Relative));
        }


        


        /// <summary>
        /// The <see cref="SelectedEvent" /> property's name.
        /// </summary>
        public const string SelectedEventPropertyName = "SelectedEvent";

        private Event _selectedEvent;

        /// <summary>
        /// Gets the SelectedEvent property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public Event SelectedEvent
        {
            get
            {
                return _selectedEvent;
            }

            set
            {
                if (_selectedEvent == value)
                {
                    return;
                }

                var oldValue = _selectedEvent;
                _selectedEvent = value;

                // Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
                RaisePropertyChanged(SelectedEventPropertyName, oldValue, value, true);
            }
        }


        /// <summary>
        /// The <see cref="SelectedSong" /> property's name.
        /// </summary>
        public const string SelectedSongPropertyName = "SelectedSong";

        private Song _selectedSong;

        /// <summary>
        /// Gets the SelectedSong property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public Song SelectedSong
        {
            get
            {
                return _selectedSong;
            }

            set
            {
                if (_selectedSong == value)
                {
                    return;
                }

                var oldValue = _selectedSong;
                _selectedSong = value;

                // Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
                RaisePropertyChanged(SelectedSongPropertyName, oldValue, value, true);
            }
        }



        /// <summary>
        /// The <see cref="AboutText" /> property's name.
        /// </summary>
        public const string AboutTextPropertyName = "AboutText";

        private string _aboutText = "";

        /// <summary>
        /// Gets the AboutText property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public string AboutText
        {
            get
            {
                return _aboutText;
            }

            set
            {
                if (_aboutText == value)
                {
                    return;
                }

                var oldValue = _aboutText;
                _aboutText = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(AboutTextPropertyName);
            }
        }


        /// <summary>
        /// The <see cref="SongList" /> property's name.
        /// </summary>
        public const string SongListPropertyName = "SongList";

        private ObservableCollection<Song> _songList;

        /// <summary>
        /// Gets the SongList property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public ObservableCollection<Song> SongList
        {
            get
            {
                return _songList;
            }

            set
            {
                if (_songList == value)
                {
                    return;
                }

                var oldValue = _songList;
                _songList = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(SongListPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="Events" /> property's name.
        /// </summary>
        public const string EventsPropertyName = "Events";

        private ObservableCollection<Event> _events;

        /// <summary>
        /// Gets the Events property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public ObservableCollection<Event> Events
        {
            get
            {
                return _events;
            }

            set
            {
                if (_events == value)
                {
                    return;
                }

                var oldValue = _events;
                _events = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(EventsPropertyName);

            }
        }


        /// <summary>
        /// The <see cref="Photos" /> property's name.
        /// </summary>
        public const string PhotosPropertyName = "Photos";

        private ObservableCollection<Photo> _photos;

        /// <summary>
        /// Gets the Photos property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public ObservableCollection<Photo> Photos
        {
            get
            {
                return _photos;
            }

            set
            {
                if (_photos == value)
                {
                    return;
                }

                var oldValue = _photos;
                _photos = value;

                RaisePropertyChanged(PhotosPropertyName, oldValue, _photos, true);
            }
        }


        /// <summary>
        /// The <see cref="Tweets" /> property's name.
        /// </summary>
        public const string TweetsPropertyName = "Tweets";

        private ObservableCollection<Tweet> _tweets;

        /// <summary>
        /// Gets the Tweets property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public ObservableCollection<Tweet> Tweets
        {
            get
            {
                return _tweets;
            }

            set
            {
                if (_tweets == value)
                {
                    return;
                }

                var oldValue = _tweets;
                _tweets = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(TweetsPropertyName);
                
            }
        }
    }
}